package com.jingdong.api;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jingdong.api.model.*;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 京东配送API SDK
 *
 * @author 林生
 * @version 1.0.0
 */
public class JingdongApiSDK {
    
    private static final Logger logger = LoggerFactory.getLogger(JingdongApiSDK.class);
    
    /**
     * 版本号
     */
    public static final String VERSION = "1.0.0";
    
    /**
     * API地址配置
     */
    public static final String API_BASE_TEST = "https://api-test.hiboos.com";
    public static final String API_BASE_SANDBOX = "https://api-sandbox.hiboos.com";
    public static final String API_BASE_PROD = "https://api.hiboos.com";
    
    private final ApiConfig config;
    private final OkHttpClient httpClient;
    private final ObjectMapper objectMapper;
    
    /**
     * 构造函数
     * 
     * @param config 配置对象
     */
    public JingdongApiSDK(ApiConfig config) {
        this.config = config;
        this.objectMapper = new ObjectMapper();
        this.httpClient = createHttpClient();
        
        logger.info("京东配送API SDK初始化完成 - 版本: {}, 环境: {}", VERSION, 
                config.isSandboxMode() ? "沙箱" : "生产");
    }
    
    /**
     * 创建HTTP客户端
     */
    private OkHttpClient createHttpClient() {
        return new OkHttpClient.Builder()
                .connectTimeout(config.getTimeout(), TimeUnit.SECONDS)
                .readTimeout(config.getTimeout(), TimeUnit.SECONDS)
                .writeTimeout(config.getTimeout(), TimeUnit.SECONDS)
                .build();
    }
    
    /**
     * 生成签名
     * 
     * @param params 请求参数
     * @return 签名
     */
    private String generateSign(Map<String, Object> params) {
        // 移除签名参数
        params.remove("sign");
        
        // 按key排序
        TreeMap<String, Object> sortedParams = new TreeMap<>(params);
        
        // 拼接参数字符串
        StringBuilder stringToBeSigned = new StringBuilder(config.getAppSecret());
        for (Map.Entry<String, Object> entry : sortedParams.entrySet()) {
            Object value = entry.getValue();
            if (value != null && !value.toString().isEmpty()) {
                stringToBeSigned.append(entry.getKey()).append(value);
            }
        }
        stringToBeSigned.append(config.getAppSecret());
        
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] hash = md.digest(stringToBeSigned.toString().getBytes());
            StringBuilder hexString = new StringBuilder();
            
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            
            return hexString.toString().toUpperCase();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5算法不支持", e);
        }
    }
    
    /**
     * 发送HTTP请求
     * 
     * @param method API方法名
     * @param params 请求参数
     * @return 响应结果
     * @throws IOException 请求异常
     */
    private Map<String, Object> request(String method, Map<String, Object> params) throws IOException {
        String url = getBaseUrl() + "/api/" + method;
        
        // 公共参数
        Map<String, Object> commonParams = new HashMap<>();
        commonParams.put("app_key", config.getAppKey());
        commonParams.put("method", method);
        commonParams.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        commonParams.put("format", "json");
        commonParams.put("v", "1.0");
        commonParams.put("sign_method", "md5");
        
        // 合并参数
        Map<String, Object> allParams = new HashMap<>(commonParams);
        if (params != null) {
            allParams.putAll(params);
        }
        
        // 生成签名
        allParams.put("sign", generateSign(allParams));
        
        // 构建表单数据
        FormBody.Builder formBuilder = new FormBody.Builder();
        for (Map.Entry<String, Object> entry : allParams.entrySet()) {
            formBuilder.add(entry.getKey(), entry.getValue().toString());
        }
        
        RequestBody requestBody = formBuilder.build();
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .addHeader("User-Agent", config.getUserAgent())
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .build();
        
        try (Response response = httpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("HTTP错误: " + response.code());
            }
            
            String responseBody = response.body().string();
            Map<String, Object> result = objectMapper.readValue(responseBody, 
                    new TypeReference<Map<String, Object>>() {});
            
            // 记录API调用日志
            if (config.isEnableLog()) {
                logger.info("JingdongAPI Request - Method: {}, Params: {}, Response: {}", 
                        method, allParams, result);
            }
            
            return result;
        } catch (Exception e) {
            logger.error("JingdongAPI Error - Method: {}, Params: {}, Error: {}", 
                    method, allParams, e.getMessage());
            throw e;
        }
    }
    
    /**
     * 获取基础URL
     */
    private String getBaseUrl() {
        return config.isSandboxMode() ? API_BASE_SANDBOX : API_BASE_PROD;
    }
    
    /**
     * 转换坐标格式
     * 将普通坐标转换为火星坐标*10^6格式
     */
    private long convertCoordinate(Double coordinate) {
        if (coordinate == null) {
            return 0;
        }
        return Math.round(coordinate * 1000000);
    }
    
    /**
     * 转换重量格式
     * 将重量转换为克(g)
     */
    private long convertWeight(Double weight) {
        if (weight == null) {
            return 0;
        }
        return Math.round(weight * 1000);
    }
    
    /**
     * 1. 申请成为配送商
     * 
     * @param merchantInfo 商户信息
     * @return API结果
     */
    public ApiResult applyMerchant(MerchantInfo merchantInfo) {
        merchantInfo.validate();
        
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("merchant_name", merchantInfo.getMerchantName());
            params.put("merchant_phone", merchantInfo.getMerchantPhone());
            params.put("merchant_address", merchantInfo.getMerchantAddress());
            params.put("business_license", merchantInfo.getBusinessLicense());
            params.put("contact_person", merchantInfo.getContactPerson());
            params.put("contact_phone", merchantInfo.getContactPhone());
            params.put("merchant_type", merchantInfo.getMerchantType());
            
            Map<String, Object> response = request("jingdong.logistics.merchant.apply", params);
            return ApiResult.fromResponse(response);
        } catch (Exception e) {
            return ApiResult.error(-1, e.getMessage());
        }
    }
    
    /**
     * 2. 查询配送商审核状态
     * 
     * @param applyId 申请ID（可为空）
     * @return API结果
     */
    public ApiResult queryMerchantStatus(String applyId) {
        try {
            Map<String, Object> params = new HashMap<>();
            if (applyId != null && !applyId.trim().isEmpty()) {
                params.put("apply_id", applyId);
            }
            
            Map<String, Object> response = request("jingdong.logistics.merchant.query", params);
            return ApiResult.fromResponse(response);
        } catch (Exception e) {
            return ApiResult.error(-1, e.getMessage());
        }
    }
    
    /**
     * 查询配送商审核状态（无参数版本）
     */
    public ApiResult queryMerchantStatus() {
        return queryMerchantStatus(null);
    }
    
    /**
     * 3. 创建配送订单（发单）
     * 
     * @param orderData 订单数据
     * @return API结果
     */
    public ApiResult createOrder(OrderData orderData) {
        orderData.validate();
        
        try {
            Map<String, Object> params = new HashMap<>();
            
            // 必填参数
            params.put("tradeOrderSource", orderData.getTradeOrderSource() != null ? orderData.getTradeOrderSource() : 1);
            params.put("orderId", orderData.getOrderId());
            params.put("serviceCode", orderData.getServiceCode() != null ? orderData.getServiceCode() : "STANDARD");
            params.put("recipientName", orderData.getRecipientName());
            params.put("recipientPhone", orderData.getRecipientPhone());
            params.put("recipientAddress", orderData.getRecipientAddress());
            params.put("recipientLng", convertCoordinate(orderData.getRecipientLng()));
            params.put("recipientLat", convertCoordinate(orderData.getRecipientLat()));
            params.put("prebook", orderData.getPrebook() != null ? orderData.getPrebook() : 0);
            params.put("totalWeight", convertWeight(orderData.getTotalWeight()));
            params.put("senderLng", convertCoordinate(orderData.getSenderLng()));
            params.put("senderLat", convertCoordinate(orderData.getSenderLat()));
            params.put("senderName", orderData.getSenderName());
            params.put("senderContract", orderData.getSenderPhone());
            params.put("senderAddressDetail", orderData.getSenderAddress());
            params.put("operatorName", orderData.getOperatorName() != null ? orderData.getOperatorName() : orderData.getSenderName());
            params.put("carrierMerchantId", config.getMerchantNo());
            
            // 扩展信息
            if (orderData.getExtInfo() != null) {
                try {
                    params.put("extInfo", objectMapper.writeValueAsString(orderData.getExtInfo()));
                } catch (JsonProcessingException e) {
                    params.put("extInfo", "{}");
                }
            } else {
                params.put("extInfo", "{}");
            }
            
            // 可选参数
            addOptionalParam(params, "tradeOrderId", orderData.getTradeOrderId());
            addOptionalParam(params, "orderSequence", orderData.getOrderSequence());
            addOptionalParam(params, "preDeliveryFee", orderData.getPreDeliveryFee());
            addOptionalParam(params, "expectedDeliveryTime", orderData.getExpectedDeliveryTime());
            addOptionalParam(params, "expectedPickupTime", orderData.getExpectedPickupTime());
            addOptionalParam(params, "expectedLeftDeliveryTime", orderData.getExpectedLeftDeliveryTime());
            addOptionalParam(params, "expectedRightDeliveryTime", orderData.getExpectedRightDeliveryTime());
            addOptionalParam(params, "insuredMark", orderData.getInsuredMark());
            addOptionalParam(params, "totalValue", orderData.getTotalValue());
            addOptionalParam(params, "totalVolume", orderData.getTotalVolume());
            addOptionalParam(params, "riderPickMethod", orderData.getRiderPickMethod());
            addOptionalParam(params, "tipFee", orderData.getTipFee());
            addOptionalParam(params, "orderRemark", orderData.getOrderRemark());
            addOptionalParam(params, "shopRemark", orderData.getShopRemark());
            addOptionalParam(params, "carrierShopId", orderData.getCarrierShopId());
            
            if (orderData.getOperatorPhone() != null) {
                params.put("operatorContract", orderData.getOperatorPhone());
            }
            
            addOptionalParam(params, "carModelCode", orderData.getCarModelCode());
            addOptionalParam(params, "riderInfo", orderData.getRiderInfo());
            addOptionalParam(params, "category", orderData.getCategory());
            
            // 物品明细
            if (orderData.getGoodsDetails() != null) {
                try {
                    params.put("goodsDetails", objectMapper.writeValueAsString(orderData.getGoodsDetails()));
                } catch (JsonProcessingException e) {
                    // 忽略序列化失败
                }
            }
            
            Map<String, Object> response = request("hiboos.order.create", params);
            return ApiResult.fromResponse(response);
        } catch (Exception e) {
            return ApiResult.error(-1, e.getMessage());
        }
    }
    
    /**
     * 添加可选参数
     */
    private void addOptionalParam(Map<String, Object> params, String key, Object value) {
        if (value != null) {
            params.put(key, value);
        }
    }
    
    /**
     * 4. 查询订单状态
     * 
     * @param outOrderId 外部订单号
     * @param jdOrderId 京东订单号
     * @return API结果
     */
    public ApiResult queryOrder(String outOrderId, String jdOrderId) {
        if ((outOrderId == null || outOrderId.trim().isEmpty()) && 
            (jdOrderId == null || jdOrderId.trim().isEmpty())) {
            return ApiResult.error(-1, "外部订单号和京东订单号至少提供一个");
        }
        
        try {
            Map<String, Object> params = new HashMap<>();
            if (outOrderId != null && !outOrderId.trim().isEmpty()) {
                params.put("out_order_id", outOrderId);
            }
            if (jdOrderId != null && !jdOrderId.trim().isEmpty()) {
                params.put("jd_order_id", jdOrderId);
            }
            
            Map<String, Object> response = request("jingdong.logistics.order.query", params);
            return ApiResult.fromResponse(response);
        } catch (Exception e) {
            return ApiResult.error(-1, e.getMessage());
        }
    }
    
    /**
     * 查询订单状态（仅外部订单号）
     */
    public ApiResult queryOrder(String outOrderId) {
        return queryOrder(outOrderId, null);
    }
    
    /**
     * 5. 取消订单
     * 
     * @param outOrderId 外部订单号
     * @param cancelReason 取消原因
     * @return API结果
     */
    public ApiResult cancelOrder(String outOrderId, String cancelReason) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("out_order_id", outOrderId);
            params.put("cancel_reason", cancelReason != null ? cancelReason : "用户取消");
            
            Map<String, Object> response = request("jingdong.logistics.order.cancel", params);
            return ApiResult.fromResponse(response);
        } catch (Exception e) {
            return ApiResult.error(-1, e.getMessage());
        }
    }
    
    /**
     * 取消订单（默认原因）
     */
    public ApiResult cancelOrder(String outOrderId) {
        return cancelOrder(outOrderId, "用户取消");
    }
    
    /**
     * 6. 骑手位置查询
     * 
     * @param outOrderId 外部订单号
     * @return API结果
     */
    public ApiResult queryRiderLocation(String outOrderId) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("out_order_id", outOrderId);
            
            Map<String, Object> response = request("jingdong.logistics.rider.location", params);
            return ApiResult.fromResponse(response);
        } catch (Exception e) {
            return ApiResult.error(-1, e.getMessage());
        }
    }
    
    /**
     * 7. 预下单接口（获取运费）
     * 
     * @param orderData 订单数据
     * @return API结果
     */
    public ApiResult preOrder(Map<String, Object> orderData) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("cargo_type", orderData.getOrDefault("cargo_type", "1"));
            params.put("cargo_weight", orderData.get("cargo_weight"));
            params.put("cargo_num", orderData.getOrDefault("cargo_num", "1"));
            params.put("cargo_price", orderData.get("cargo_price"));
            
            try {
                params.put("pickup_info", objectMapper.writeValueAsString(orderData.get("pickup_info")));
                params.put("delivery_info", objectMapper.writeValueAsString(orderData.get("delivery_info")));
            } catch (JsonProcessingException e) {
                return ApiResult.error(-1, "序列化取货或配送信息失败");
            }
            
            params.put("expected_pickup_time", orderData.get("expected_pickup_time"));
            params.put("expected_delivery_time", orderData.get("expected_delivery_time"));
            
            Map<String, Object> response = request("jingdong.logistics.order.preorder", params);
            return ApiResult.fromResponse(response);
        } catch (Exception e) {
            return ApiResult.error(-1, e.getMessage());
        }
    }
    
    /**
     * 8. 查询可配送范围
     * 
     * @param lng 经度
     * @param lat 纬度
     * @return API结果
     */
    public ApiResult queryServiceArea(String lng, String lat) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("longitude", lng);
            params.put("latitude", lat);
            
            Map<String, Object> response = request("jingdong.logistics.area.query", params);
            return ApiResult.fromResponse(response);
        } catch (Exception e) {
            return ApiResult.error(-1, e.getMessage());
        }
    }
    
    /**
     * 9. 查询历史订单列表
     * 
     * @param condition 查询条件
     * @return API结果
     */
    public ApiResult queryOrderList(Map<String, Object> condition) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("page_size", condition.getOrDefault("page_size", 20));
            params.put("page_no", condition.getOrDefault("page_no", 1));
            
            // 可选参数
            String[] optionalFields = {"start_time", "end_time", "order_status"};
            for (String field : optionalFields) {
                if (condition.containsKey(field)) {
                    params.put(field, condition.get(field));
                }
            }
            
            Map<String, Object> response = request("jingdong.logistics.order.list", params);
            return ApiResult.fromResponse(response);
        } catch (Exception e) {
            return ApiResult.error(-1, e.getMessage());
        }
    }
    
    /**
     * 查询历史订单列表（无条件）
     */
    public ApiResult queryOrderList() {
        return queryOrderList(new HashMap<>());
    }
    
    /**
     * 10. 订单追加小费
     * 
     * @param outOrderId 外部订单号
     * @param tips 小费金额
     * @return API结果
     */
    public ApiResult addTips(String outOrderId, String tips) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("out_order_id", outOrderId);
            params.put("tips", tips);
            
            Map<String, Object> response = request("jingdong.logistics.order.addtips", params);
            return ApiResult.fromResponse(response);
        } catch (Exception e) {
            return ApiResult.error(-1, e.getMessage());
        }
    }
    
    /**
     * 11. 订单催单
     * 
     * @param outOrderId 外部订单号
     * @return API结果
     */
    public ApiResult urgeOrder(String outOrderId) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("out_order_id", outOrderId);
            
            Map<String, Object> response = request("jingdong.logistics.order.urge", params);
            return ApiResult.fromResponse(response);
        } catch (Exception e) {
            return ApiResult.error(-1, e.getMessage());
        }
    }
    
    /**
     * 12. 获取订单详情
     * 
     * @param outOrderId 外部订单号
     * @return API结果
     */
    public ApiResult getOrderDetail(String outOrderId) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("out_order_id", outOrderId);
            
            Map<String, Object> response = request("jingdong.logistics.order.detail", params);
            return ApiResult.fromResponse(response);
        } catch (Exception e) {
            return ApiResult.error(-1, e.getMessage());
        }
    }
    
    /**
     * 13. 验证回调签名
     * 
     * @param data 回调数据
     * @param signature 签名
     * @return 验证结果
     */
    public boolean verifyCallback(Map<String, Object> data, String signature) {
        String localSign = generateSign(new HashMap<>(data));
        return localSign.equals(signature);
    }
    
    /**
     * 获取配置信息
     * 
     * @return 配置信息
     */
    public Map<String, Object> getConfig() {
        Map<String, Object> configInfo = new HashMap<>();
        configInfo.put("app_key", config.getAppKey());
        configInfo.put("merchant_no", config.getMerchantNo());
        configInfo.put("sandbox_mode", config.isSandboxMode());
        configInfo.put("base_url", getBaseUrl());
        return configInfo;
    }
    
    /**
     * 测试API连接
     * 
     * @return API结果
     */
    public ApiResult testConnection() {
        try {
            ApiResult result = queryMerchantStatus();
            if (result.isSuccess()) {
                return ApiResult.success(result.getData(), "API连接正常");
            } else {
                return result;
            }
        } catch (Exception e) {
            return ApiResult.error(-1, "API连接失败: " + e.getMessage());
        }
    }
    
    /**
     * 关闭资源
     */
    public void close() {
        if (httpClient != null) {
            httpClient.dispatcher().executorService().shutdown();
            httpClient.connectionPool().evictAll();
        }
        
        logger.info("京东配送API SDK资源已释放");
    }
}
